/**
  ETFRoot project, Anyang Normal University && IMP-CAS
  \class ETFOfflineSource
  \brief to process offline data, an abstract base class
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-09-28
  \date 2021-12-15 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2021-09-28   <td>Asia Sun    <td>file created                  </tr>
  </table>

  \copyright Copyright (c) 2021 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#include <iostream>
#include <libgen.h>
#include <regex> // regular expression since c++11
#include "FairRootManager.h"
#include "FairSink.h"

#include "ETFOfflineSource.h"
#include "ETFUnpacker.h"
#include "ETFMsg.h"

using std::cout;
using std::flush;
using std::regex;

ClassImp(ETFOfflineSource);

ETFOfflineSource::ETFOfflineSource() : FairOnlineSource(), fType(SourceType::kGENERAL){}

/// read event i
int ETFOfflineSource::ReadEvent(UInt_t i){
  static unsigned i0 = 0;
  if(0 == i) i += i0++; // so that if i is always 0, it'd be incrementing to the maxEvNo
  if(i < 0) ETFMsg::Error("ETFOfflineSource", "ReadEvent: Requested event index %u is minus.", i);

  for(auto &m : fMap){
    int j = -2;
    while((j = m.first->GetOneEvent(m.second)) != -1 && j < i)
      cout << "Skipping event " << j << "\r" << flush;
    if(j == i) m.first->Unpack();
    else if(-1 == j) return 1;
    else ETFMsg::Warn("ETFOfflineSource", "ReadEvent: ev_start(%u) < minimal(%d)", i, j);
  } // end for

  FinishEvent();

  return 0;
} // end member function ReadEvent

// pattern: d{8}_d{4}.dat; e.g. 20180708_0153.dat
bool ETFOfflineSource::IsPXIFileName(const string &file, bool isStop){
  char name[128]; strcpy(name, file.c_str());
  bool result = regex_match(basename(name), regex("^\\d{8}_\\d{4}\\.dat$"));
  if(!result && isStop)
    ETFMsg::Error("ETFOfflineSource",
      "SetPXIDataFile: %s not of a PXI filename format (e.g. 20180708_0153.dat)", file);
  return result;
} // end membe function IsPXIFileName

// pattern: d{8}.d{3}; e.g. 20180708.003
bool ETFOfflineSource::IsVMEFileName(const string &file, bool isStop){
  char name[128]; strcpy(name, file.c_str());
  bool result = regex_match(basename(name), regex("^\\d{8}\\.\\d{3}$"));
  if(!result && isStop)
    ETFMsg::Error("ETFOfflineSource",
      "SetVMEDataFile: %s not of a VME filename format (e.g. 20180708.003)", file);
  return result;
} // end member function IsPXIFileName

void ETFOfflineSource::PrintSummary(){
  ETFMsg::Logo();
  dynamic_cast<ETFUnpacker *>(fUnpackers->At(0))->PrintSummary();

  cout << "\033[33;1m:)\033[0m Unpacked data have been written into ";
  cout << "\033[1m" << FairRootManager::Instance()->GetSink()->GetFileName().Data();
  cout << " \033[33;1m:)\033[0m.\n";
} // end member function PrintSummary

ETFOfflineSource::~ETFOfflineSource(){}

///< close the input file
void ETFOfflineSource::Close(){
  for(auto &m : fMap) fclose(m.second);
} // end member function Close
